﻿#pragma once
#include "AsBasicGlobal.h"
#include "AsDefine.h"
#include "AsDebug.h"
#ifndef asMax
#define asMax(a,b)            (((a) > (b)) ? (a) : (b))
#endif
#ifndef asMin
#define asMin(a,b)            (((a) < (b)) ? (a) : (b))
#endif

#define asCatchn(__fun__, __rtn__) \
	if (__fun__) { \
		std::string info = std::string("[AsCatcher] catch \"") + #__fun__ +"\" action \"" + #__rtn__ + "\"."; \
		if (AsCatcher::isOutputConsole()) \
			AsDebug() << info; \
		__rtn__; \
	}

#define asCatch(__fun__, __rtn__) \
	if (__fun__) { \
		std::string info = std::string("[AsCatcher] catch \"") + #__fun__ +"\" action \"" + #__rtn__ + "\"."; \
		if (AsCatcher::isOutputConsole()) \
			AsDebug() << info; \
		if (AsCatcher::isThrow()) \
			throw info; \
		__rtn__; \
	}
#define asCatcher(__fun__, __rtn__) asCatch(AsCatcher::__fun__, __rtn__)
#define asCatch_NoReturn void()
#define asCatch_VoidReturn return void()
#define asCatch_FalseReturn return false
#define asCatch_TrueReturn return true
#define asCatch_NullReturn return nullptr
#define asCatch_isEqual_float(__p1__, __p2__) (fabs(__p1__ - __p2__) * 100000.f <= asMin(fabs(__p1__), fabs(__p2__)))
#define asCatch_isEqual_double(__p1__, __p2__) (fabs(__p1__ - __p2__) * 1000000000000. <= asMin(fabs(__p1__), fabs(__p2__)))
/* 
	捕捉器（基础类/调试类）  |  开发者：姜一  |  ^_^  
*/
__AS_JY(Update 2023.1.7)
class AS_BASIC_EXPORT AsCatcher {
public:
	enum CatchType {
		emNone,
		emNull, emNotNull, emTrue, emFalse,
		emZero, emEqual, emNotEqual,
		emGreaterThan, emNotGreaterThan,
		emLessThan, emNotLessThan,
		emEmpty, emIsEmpty
	};

private:
	static bool IsThrow;
	static bool IsOutputConsole;
	static int  LastCatching;

public:
	static void setThrow(bool enable);
	static void setOutputConsole(bool enable);
	static bool isThrow();
	static bool isOutputConsole();
	static int  last_catching();

public:
	static bool Null(void* ptr);
	static bool NotNull(void* ptr);
	static bool True(bool b);
	static bool False(bool b);

public:
	template<typename _Type>
	static bool Zero(const _Type& a) {
		if (a == 0) {
			LastCatching = emZero;
		}
		return a == 0;
	}
	static bool Zero(float a);
	static bool Zero(double a);
	template<typename _Type>
	static bool Equal(const _Type& a, const _Type& b) {
		if (a == b) {
			LastCatching = emEqual;
		}
		return a == b;
	}
	static bool Equal(float a, float b);
	static bool Equal(double a, double b);
	template<typename _Type>
	static bool NotEqual(const _Type& a, const _Type& b) {
		if (a != b) {
			LastCatching = emNotEqual;
		}
		return a != b;
	}
	static bool NotEqual(float a, float b);
	static bool NotEqual(double a, double b);
	template<typename _Type>
	static bool GreaterThan(const _Type& a, const _Type& b) {
		if (a > b) {
			LastCatching = emGreaterThan;
		}
		return a > b;
	}
	template<typename _Type>
	static bool NotGreaterThan(const _Type& a, const _Type& b) {
		if (a <= b) {
			LastCatching = emNotGreaterThan;
		}
		return a <= b;
	}
	static bool NotGreaterThan(float a, float b);
	static bool NotGreaterThan(double a, double b);
	template<typename _Type>
	static bool LessThan(const _Type& a, const _Type& b) {
		if (a < b) {
			LastCatching = emLessThan;
		}
		return a < b;
	}
	template<typename _Type>
	static bool NotLessThan(const _Type& a, const _Type& b) {
		if (a >= b) {
			LastCatching = emNotLessThan;
		}
		return a >= b;
	}
	static bool NotLessThan(float a, float b);
	static bool NotLessThan(double a, double b);
	template<typename _Type>
	static bool Empty(const _Type& content) {
		if (content.empty()) {
			LastCatching = emEmpty;
		}
		return content.empty();
	}
	template<typename _Type>
	static bool IsEmpty(const _Type& object) {
		if (object.isEmpty()) {
			LastCatching = emIsEmpty;
		}
		return object.isEmpty();
	}

};

